namespace SimpleWebServices.Configuration
{
    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Diagnostics.CodeAnalysis;
    using System.Globalization;
    using System.Xml;
    using System.Xml.XPath;

    [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Default", Justification = "This is my preferred naming.")]
    public sealed class Default
    {
        public Default()
        {
            this.Objects = ConfigurationManager.GetSection("simplewebservices/default") as Dictionary<string, IXPathNavigable>;
        }

        public Dictionary<string, IXPathNavigable> Objects
        {
            get;
            private set;
        }

        public static void Clear()
        {
            new Default().Objects.Clear();
        }

        public static void Register<T>(string configuration)
        {
            Register<T>(null as string, configuration);
        }

        public static void Register<T>(IXPathNavigable configuration)
        {
            Register<T>(null as string, configuration);
        }

        public static void Register<T>(string name, string configuration)
        {
            if (null == configuration)
            {
                throw new ArgumentNullException("configuration");
            }
            else if (0 == configuration.Length)
            {
                throw new ArgumentOutOfRangeException("configuration");
            }

            XmlDocument xml = new XmlDocument();
            xml.LoadXml(configuration);

            Register<T>(name, xml);
        }

        public static void Register<T>(string name, IXPathNavigable configuration)
        {
            if (null == configuration)
            {
                throw new ArgumentNullException("configuration");
            }

            new Default().Objects[ToKey<T>(name)] = configuration;
        }

        public static void Reset()
        {
            ConfigurationManager.RefreshSection("simplewebservices/default");
        }

        public T Object<T>()
        {
            return this.Object<T>(null);
        }

        public T Object<T>(string name)
        {
            T result = default(T);

            if (null != this.Objects)
            {
                string key = ToKey<T>(name);
                if (this.Objects.ContainsKey(key))
                {
                    result = this.Objects[key].CreateNavigator().OuterXml.Deserialize<T>();
                }
            }

            return result;
        }

        private static string ToKey<T>(string name)
        {
            string type = typeof(T).FullName;

            return string.IsNullOrEmpty(name)
                ? type
                : string.Format(CultureInfo.InvariantCulture, "{0} : {1}", type, name);
        }
    }
}